import java.awt.event.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;

import com.limegroup.gnutella.*;

/**
 * Limewire server.
 */
class Limewire extends LocalServer implements Main.Listener {

  /** 
   * Keep a list of search results whenever they show up, and empty
   * them whenever a <code>CheckSearch</code> msg is sent.
   */
  private final List<SearchResult> searchResults = new Vector<SearchResult>();

  static class SearchResult {
    private final String magnetLink;
    private final RemoteFileDesc rfd;
    SearchResult(String magnetLink, RemoteFileDesc rfd) {
      this.magnetLink = magnetLink;
      this.rfd = rfd;
    }
    public final String getMagnetLink() {
      return magnetLink;
    }
    public final RemoteFileDesc getRemoteFileDesc() {
      return rfd;
    }
  }

  /** Starts a search */
  private class SearchHandler extends AbstractHandler {

    public String handle(Map<String,String> args) {
      // First clear all previous results
      searchResults.clear();

      // Do the search
      String q = getArg(args,"q");
      Main.search(q);
      return "ok";
    }

    SearchHandler() {
      super("Search");
    }
  }

  /** Sotp a search */
  private class StopSearchHandler extends AbstractHandler {

    public String handle(Map<String,String> args) {
      // TODO: stop search
      return "ok";
    }

    StopSearchHandler() {
      super("StopSearch");
    }
  }

  /** Checks on search results because the search is asynchronous */
  private class CheckSearchHandler extends AbstractHandler {

    public String handle(Map<String,String> args) {

      StringBuffer result = new StringBuffer();
      String sep = "|";
      String linesep = "\t";
      synchronized(searchResults) {
        note("Have " + searchResults.size() + " search result(s)");
        while (!searchResults.isEmpty()) {
          SearchResult sr = searchResults.remove(0); // not efficient, but who cares
          RemoteFileDesc rfd = sr.getRemoteFileDesc();
          String magnetLink = sr.getMagnetLink();
          result.append(magnetLink);
          result.append(sep).append(rfd.getFileName());
          result.append(linesep);
        }
      }      
      return result.toString();
    }

    CheckSearchHandler() {
      super("CheckSearch");
    }
  }

  Handler[] getHandlers() {
    return new Handler[] {
      new SearchHandler(),
      new StopSearchHandler(),
      new CheckSearchHandler(),
    };
  }

  /*
   * Main.Listener
   */
  public void process(String magnetLink, RemoteFileDesc rfd) {
    note(" >>> link: " + magnetLink);
    note(" >>> rfd: " + rfd);
    searchResults.add(new SearchResult(magnetLink,rfd));
    note("process(): " + searchResults.size() + " search result(s)");
  }

  protected void beforeWeStart(final String[] args) {
    Main.init();
    Main.addListener(this);
  }

  protected void beforeWeStop() {
    Main.shutdown();
  }


  public static void main(String args[]) {
    new Limewire().realMain(args);
  }
  
}
